FlatKitOutline.shader 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. Shader "Hidden/FlatKit/OutlineFilter"
  2. {
  3. Properties
  4. {
  5. [HideInInspector]_BaseMap ("Base (RGB)", 2D) = "white" {}
  6. _EdgeColor ("Outline Color", Color) = (1, 1, 1, 1)
  7. _Thickness ("Thickness", Range(0, 5)) = 1
  8. [Space(15)]
  9. [Toggle(OUTLINE_USE_DEPTH)]_UseDepth ("Use Depth", Float) = 1
  10. _DepthThresholdMin ("Min Depth Threshold", Range(0, 1)) = 0
  11. _DepthThresholdMax ("Max Depth Threshold", Range(0, 1)) = 0.25
  12. [Space(15)]
  13. [Toggle(OUTLINE_USE_NORMALS)]_UseNormals ("Use Normals", Float) = 0
  14. _NormalThresholdMin ("Min Normal Threshold", Range(0, 1)) = 0.5
  15. _NormalThresholdMax ("Max Normal Threshold", Range(0, 1)) = 1.0
  16. [Space(15)]
  17. [Toggle(OUTLINE_USE_COLOR)]_UseColor ("Use Color", Float) = 0
  18. _ColorThresholdMin ("Min Color Threshold", Range(0, 1)) = 0
  19. _ColorThresholdMax ("Max Color Threshold", Range(0, 1)) = 0.25
  20. [Space(15)]
  21. [Toggle(OUTLINE_ONLY)]_OutlineOnly ("Outline Only", Float) = 0
  22. }
  23. SubShader
  24. {
  25. Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline"}
  26. LOD 100
  27. ZWrite Off Cull Off
  28. Pass
  29. {
  30. Name "Outline"
  31. HLSLPROGRAM
  32. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
  33. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
  34. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"
  35. #pragma shader_feature OUTLINE_USE_DEPTH
  36. #pragma shader_feature OUTLINE_USE_NORMALS
  37. #pragma shader_feature OUTLINE_USE_COLOR
  38. #pragma shader_feature OUTLINE_ONLY
  39. #pragma shader_feature RESOLUTION_INVARIANT_THICKNESS
  40. #pragma multi_compile _ _USE_DRAW_PROCEDURAL
  41. uniform half _Thickness;
  42. uniform half4 _EdgeColor;
  43. uniform half _DepthThresholdMin, _DepthThresholdMax;
  44. uniform half _NormalThresholdMin, _NormalThresholdMax;
  45. uniform half _ColorThresholdMin, _ColorThresholdMax;
  46. TEXTURE2D_X(_CameraColorTexture);
  47. SAMPLER(sampler_CameraColorTexture);
  48. // #define OUTLINE_USE_TRANSPARENT_DEPTH
  49. #ifdef OUTLINE_USE_TRANSPARENT_DEPTH
  50. TEXTURE2D_X(_CameraTransparentDepthTexture);
  51. #endif
  52. float4 _SourceSize;
  53. // Z buffer depth to linear 0-1 depth
  54. // Handles orthographic projection correctly
  55. float Linear01Depth(float z)
  56. {
  57. const float isOrtho = unity_OrthoParams.w;
  58. const float isPers = 1.0 - unity_OrthoParams.w;
  59. z *= _ZBufferParams.x;
  60. return (1.0 - isOrtho * z) / (isPers * z + _ZBufferParams.y);
  61. }
  62. float SampleDepth(float2 uv)
  63. {
  64. float d = SampleSceneDepth(uv);
  65. #ifdef OUTLINE_USE_TRANSPARENT_DEPTH
  66. d += SAMPLE_TEXTURE2D_X(_CameraTransparentDepthTexture, sampler_CameraColorTexture, UnityStereoTransformScreenSpaceTex(uv)).r;
  67. #endif
  68. return Linear01Depth(d);
  69. }
  70. float4 SampleCameraColor(float2 uv)
  71. {
  72. return SAMPLE_TEXTURE2D_X(_CameraColorTexture, sampler_CameraColorTexture, UnityStereoTransformScreenSpaceTex(uv));
  73. }
  74. float4 Outline(float2 uv)
  75. {
  76. float4 original = SampleCameraColor(uv);
  77. const float offset_positive = +ceil(_Thickness * 0.5f);
  78. const float offset_negative = -floor(_Thickness * 0.5f);
  79. #if RESOLUTION_INVARIANT_THICKNESS
  80. const float screen_ratio = _SourceSize.x / _SourceSize.y;
  81. const float2 texel_size = 1.0 / 800.0 * float2(1.0, screen_ratio);
  82. #else
  83. const float2 texel_size = _SourceSize.zw;
  84. #endif
  85. float left = texel_size.x * offset_negative;
  86. float right = texel_size.x * offset_positive;
  87. float top = texel_size.y * offset_negative;
  88. float bottom = texel_size.y * offset_positive;
  89. const float2 uv0 = uv + float2(left, top);
  90. const float2 uv1 = uv + float2(right, bottom);
  91. const float2 uv2 = uv + float2(right, top);
  92. const float2 uv3 = uv + float2(left, bottom);
  93. #ifdef OUTLINE_USE_DEPTH
  94. const float d0 = SampleDepth(uv0);
  95. const float d1 = SampleDepth(uv1);
  96. const float d2 = SampleDepth(uv2);
  97. const float d3 = SampleDepth(uv3);
  98. const float depth_threshold_scale = 300.0f;
  99. float d = length(float2(d1 - d0, d3 - d2)) * depth_threshold_scale;
  100. d = smoothstep(_DepthThresholdMin, _DepthThresholdMax, d);
  101. #else
  102. float d = 0.0f;
  103. #endif // OUTLINE_USE_DEPTH
  104. #ifdef OUTLINE_USE_NORMALS
  105. const float3 n0 = SampleSceneNormals(uv0);
  106. const float3 n1 = SampleSceneNormals(uv1);
  107. const float3 n2 = SampleSceneNormals(uv2);
  108. const float3 n3 = SampleSceneNormals(uv3);
  109. const float3 nd1 = n1 - n0;
  110. const float3 nd2 = n3 - n2;
  111. float n = sqrt(dot(nd1, nd1) + dot(nd2, nd2));
  112. n = smoothstep(_NormalThresholdMin, _NormalThresholdMax, n);
  113. #else
  114. float n = 0.0f;
  115. #endif // OUTLINE_USE_NORMALS
  116. #ifdef OUTLINE_USE_COLOR
  117. const float3 c0 = SampleCameraColor(uv0).rgb;
  118. const float3 c1 = SampleCameraColor(uv1).rgb;
  119. const float3 c2 = SampleCameraColor(uv2).rgb;
  120. const float3 c3 = SampleCameraColor(uv3).rgb;
  121. const float3 cd1 = c1 - c0;
  122. const float3 cd2 = c3 - c2;
  123. float c = sqrt(dot(cd1, cd1) + dot(cd2, cd2));
  124. c = smoothstep(_ColorThresholdMin, _ColorThresholdMax, c);
  125. #else
  126. float c = 0;
  127. #endif // OUTLINE_USE_COLOR
  128. const float g = max(d, max(n, c));
  129. #ifdef OUTLINE_ONLY
  130. original.rgb = lerp(1.0 - _EdgeColor.rgb, _EdgeColor.rgb, g * _EdgeColor.a);
  131. #endif // OUTLINE_ONLY
  132. float4 output;
  133. output.rgb = lerp(original.rgb, _EdgeColor.rgb, g * _EdgeColor.a);
  134. output.a = original.a;
  135. return output;
  136. }
  137. struct Attributes
  138. {
  139. float4 positionHCS : POSITION;
  140. float2 uv : TEXCOORD0;
  141. UNITY_VERTEX_INPUT_INSTANCE_ID
  142. };
  143. struct Varyings
  144. {
  145. float4 positionCS : SV_POSITION;
  146. float2 uv : TEXCOORD0;
  147. UNITY_VERTEX_OUTPUT_STEREO
  148. };
  149. Varyings vert(Attributes input)
  150. {
  151. Varyings output;
  152. UNITY_SETUP_INSTANCE_ID(input);
  153. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  154. #if _USE_DRAW_PROCEDURAL
  155. output.positionCS = float4(input.positionHCS.xyz, 1.0);
  156. #if UNITY_UV_STARTS_AT_TOP
  157. output.positionCS.y *= -1;
  158. #endif
  159. #else
  160. output.positionCS = TransformObjectToHClip(input.positionHCS.xyz);
  161. #endif
  162. output.uv = input.uv;
  163. return output;
  164. }
  165. half4 frag(Varyings input) : SV_Target
  166. {
  167. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  168. float4 c = Outline(input.uv);
  169. return c;
  170. }
  171. #pragma vertex vert
  172. #pragma fragment frag
  173. ENDHLSL
  174. }
  175. }
  176. FallBack "Diffuse"
  177. }